﻿using System;
using System.IO;
using System.Linq;

namespace WP7BackupService
{
	public class BackupServiceService : IBackupService
	{
		public string Echo(string data)
		{
			return data;
		}

		public void InitBackupSet(string application, string backupSet)
		{
			string filePath = Path.Combine(Settings.BackupFolder, application);
			if (!Directory.Exists(filePath))
				Directory.CreateDirectory(filePath);
			filePath = Path.Combine(filePath, backupSet);
			if (Directory.Exists(filePath))
				Directory.Delete(filePath, true);
			Directory.CreateDirectory(filePath);
		}

		public BackupSet GetBackupSetInfo(string application, string backupSet)
		{
			string filePath = Path.Combine(Settings.BackupFolder, application);
			filePath = Path.Combine(filePath, backupSet);
			if (!Directory.Exists(filePath))
				return null;
			// the backup set exists, let's gather the informations
			string spliSep = string.Format("\\{0}\\{1}\\", application, backupSet);
			BackupSet info = new BackupSet();
			info.Folders = Directory.GetDirectories(filePath, "*", SearchOption.AllDirectories).Select(d => d.Substring(d.IndexOf(spliSep) + spliSep.Length)).ToArray();
			info.Files = Directory.GetFiles(filePath, "*", SearchOption.AllDirectories).Select(d => d.Substring(d.IndexOf(spliSep) + spliSep.Length)).ToArray();
			return info;
		}

		public Stream DownloadStream(FileDownloadInfo fileDownloadInfoInfo)
		{
			string filePath = Path.Combine(Settings.BackupFolder, fileDownloadInfoInfo.Application);
			filePath = Path.Combine(filePath, fileDownloadInfoInfo.Set);
			filePath = Path.Combine(filePath, fileDownloadInfoInfo.Name);
			if (!File.Exists(filePath))
				return null;
			try
			{
				FileStream fileStream = File.OpenRead(filePath);
				return fileStream;
			}
			catch (IOException ex)
			{
				Console.WriteLine(String.Format("Exception while opening file: {0}\n\n{1}\n\n", filePath, ex));
				throw;
			}
		}

		public void UploadBytes(FileUploadInfo fileUploadInfoInfo)
		{
			// the file will placed in the folloing path:
			// Settings.BackupFolder\application\set\filename
			// where filename is the relative path in the isolated storage
			string filePath = Path.Combine(Settings.BackupFolder, fileUploadInfoInfo.Application);
			filePath = Path.Combine(filePath, fileUploadInfoInfo.Set);
			filePath = Path.Combine(filePath, fileUploadInfoInfo.Name);
			// extract the directory structure and create it if needed
			string dir = Path.GetDirectoryName(filePath);
			if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
				Directory.CreateDirectory(dir);
			try
			{
				using (FileStream outstream = File.Open(filePath, FileMode.Create, FileAccess.Write))
				{
					outstream.Write(fileUploadInfoInfo.Bytes, 0, fileUploadInfoInfo.Bytes.Length);
				}
			}
			catch (IOException ex)
			{
				Console.WriteLine(String.Format("Exception while writing file: {0}\n\n{1}\n\n", filePath, ex));
				throw;
			}
		}

		public void UploadStream(FileUploadStreamInfo stream)
		{
			// the file will placed in the folloing path:
			// Settings.BackupFolder\application\set\filename
			// where filename is the relative path in the isolated storage
			string filePath = Path.Combine(Settings.BackupFolder, stream.Application);
			filePath = Path.Combine(filePath, stream.Set);
			filePath = Path.Combine(filePath, stream.Name);
			// extract the directory structure and create it if needed
			string dir = Path.GetDirectoryName(filePath);
			if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
				Directory.CreateDirectory(dir);
			try
			{
				using (FileStream outstream = File.Open(filePath, FileMode.Create, FileAccess.Write))
				{
					const int bufferLen = 4096;
					byte[] buffer = new byte[bufferLen];
					int count;
					while ((count = stream.Stream.Read(buffer, 0, bufferLen)) > 0)
					{
						outstream.Write(buffer, 0, count);
					}
					stream.Stream.Close();
				}
			}
			catch (IOException ex)
			{
				Console.WriteLine(String.Format("Exception while writing file: {0}\n\n{1}\n\n", filePath, ex));
				throw;
			}
		}
	}
}